package org.lh.servlet;


import org.lh.annotation.*;
import org.lh.controller.UserController;
import org.lh.tools.ControllerHandle;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.*;

import static org.lh.tools.ControllerHandle.isController;
import static org.lh.tools.ControllerHandle.isRestController;
import static org.lh.tools.ControllerHandle.viewShow;

//分发处理器
public class DispatcherServlet extends HttpServlet {

    //类名过滤链，存储项目里面的所有class类名文件
    public List<String> classPathList=new ArrayList<String>();

    //用于存储所有controller，service类型注解的类名称
    public static Map<String,Object> instanceMap=new HashMap<String,Object>();
    //用于requestMapping信息的map
    public static Map<String,Object> requestMap=new HashMap<String, Object>();
    List<String> packageNames = new ArrayList<String>();

    public DispatcherServlet(){
        super();
    }

    //初始化操作
    @Override
    public void init(ServletConfig servletConfig){
        Class clazz=DispatcherServlet.class;
        String packageName=clazz.getPackage().getName(); //这里获取的内容是org.lh
        scanPackage("org.lh");
        try {
            filterAndInstance("org.lh.service.UserService");
            filterAndInstance("org.lh.controller.UserController");
            filterAndInstance("org.lh.controller.RestApi");
            displayList();
            ioc();
            handleRequestMapping();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
    }

    //扫描所有的文件夹内容
    public void scanPackage(String packagePath) {
        //从服务器环境中获取所有文件夹的基本路径
        String filePath = this.getClass().getClassLoader().getResource(replaceTo(packagePath)).getFile();
        System.out.println("this project "+filePath);
        displayFile(filePath);
    }

    //打印加载到集合列表里面的内容
    private void displayList(){
        for (String s : instanceMap.keySet()) {
        }
    }

    //将所有的类文件名称都加载到list集合中去
    private void displayFile(String filePath){
        File file=new File(filePath);
        System.out.println("file path is :"+file.getAbsolutePath());
        String filePathArr[]=file.list();
        for (String packageName : filePathArr) {
            File files=new File(filePath+"\\"+packageName);
            if(files.isFile()){
                System.out.println("----------"+packageName);
                File eachFile=new File(filePath+"\\"+packageName);
                //将每一份文件的路径都加入到内存当中
                classPathList.add(eachFile.getAbsolutePath());
            }else if(files.isDirectory()){
                //递归获取到class文件的地址
                displayFile(files.getAbsolutePath());
            }
        }
    }

    //初始化过滤链
    private static void filterAndInstance(String className) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        Class<?> clazz=Class.forName(className);
        //如果当前的这个类是一个Service类的话
        if(clazz.isAnnotationPresent(Service.class)){
            Object instance=clazz.newInstance();
            Service controller=clazz.getAnnotation(Service.class);
            String value=controller.value();
            instanceMap.put(value,instance);
        }
        else if(clazz.isAnnotationPresent(Controller.class)){
            Object instance=clazz.newInstance();
            Controller controller=clazz.getAnnotation(Controller.class);
            String value=controller.value();
            instanceMap.put(value,instance);
        }else if(clazz.isAnnotationPresent(RestController.class)){
            Object instance=clazz.newInstance();
            RestController restController=clazz.getAnnotation(RestController.class);
            String value=restController.value();
            instanceMap.put(value,instance);
        }
    }

    private String replaceTo(String path) {
        return path.replaceAll("\\.", "/");
    }

    private void ioc() throws IllegalAccessException {
        if(instanceMap.isEmpty()){
            return ;
        }
        for(Map.Entry<String,Object> entry:instanceMap.entrySet()){
            //拿到每一个类里面的所有属性
            Field fields[]=entry.getValue().getClass().getDeclaredFields();
            for(Field field:fields){
                field.setAccessible(true);
                if(field.isAnnotationPresent(AutoWired.class)){
                    AutoWired autoWired=field.getAnnotation(AutoWired.class);
                    //这里面拿到的是userService
                    //instanceMap里面包含有UserController,以及org.lh.controller.UserController@eb0dff
                    //set(Object obj, Object value)含义是：向obj对象的这个Field设置新值value
                    //相当于向UserController里面的UserService方法注入一个UserService的类实例
                    field.set(entry.getValue(),instanceMap.get(autoWired.value()));
                }
            }
        }
    }

    //处理所有的请求的路径，然后添加到一个Map里面去
    private void handleRequestMapping(){
        if(instanceMap.size()<0){
            return;
        }
        for(Map.Entry<String, Object> entry :instanceMap.entrySet()){
            Object obj=entry.getValue();
            if(isController(obj)||isRestController(obj)){
                //获取这个类里面的所有方法
                Method[] methods=entry.getValue().getClass().getMethods();
                for (Method method : methods) {
                    if(method.isAnnotationPresent(RequestMapping.class)){
                        RequestMapping req=method.getAnnotation(RequestMapping.class);
                       requestMap.put(req.value(),method);
                    }
                }
            }
        }
    }


    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                String url = req.getRequestURI();
                String context = req.getContextPath();
                String handleUrl = url;
                String contName = handleUrl.split("/")[1];
                String methodName = handleUrl.replace(contName, ""); //输出'//login4'
                methodName = methodName.replaceFirst("\\/", "");
                Object aimObj=instanceMap.get(contName);
                Method method = (Method) requestMap.get(methodName);
                try {
                    Parameter[] parameterps=method.getParameters();  //jdk1.8才支持
                    for (Parameter parameterp : parameterps) {
                        System.out.println(parameterp.getName());
                    }
                    //代理模式执行相应方法
                    Object result = method.invoke(aimObj, new Object[]{req, resp});
                    if(isRestController(aimObj)) { //rest接口
                        if (result != null) {
                            //视图渲染的核心函数
                            viewShow(resp,result); //这里面需要添加json解析内容
                        } else {
                            return;
                        }
                    }else if(isController(aimObj)){  //接口
                        if (result != null) {
                            //jsp的跳转
                            req.getRequestDispatcher(result.toString()).forward(req, resp);
                        } else {
                            return;
                        }
                    }
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
    }

}
